package com.lifeservice.file.service.impl;

import com.lifeservice.common.config.MinioConfig;
import com.lifeservice.common.core.domain.UploadFile;
import com.lifeservice.common.utils.DateUtils;
import com.lifeservice.common.utils.uuid.UUID;
import com.lifeservice.file.service.ISysFileService;
import io.minio.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.tika.mime.MimeType;
import org.apache.tika.mime.MimeTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

/**
 * Minio 文件存储
 *
 * @author hoperun.cable
 */
@Service
public class MinioSysFileServiceImpl implements ISysFileService {
    private static final Logger log = LoggerFactory.getLogger(MinioSysFileServiceImpl.class);

    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private MinioClient client;

    @Override
    public UploadFile uploadFile(MultipartFile file, String tableName) throws Exception {
        String filePrefix = tableName + "/" + DateUtils.dateTime() + "/" + UUID.fastUUID().toString(true);
        String extentSion = ".png";
        try {
            MimeTypes allTypes = MimeTypes.getDefaultMimeTypes();
            MimeType type = allTypes.forName(file.getContentType());
            extentSion = type.getExtension();
        } catch (Exception e) {
            extentSion = ".png";
        }
        String allFileName = filePrefix + extentSion;
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(allFileName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build();

        client.putObject(args);

        String object = minioConfig.getBucketName() + "/" + allFileName;
        // 如果cdn不为空，则url为cdnurl
        String url = StringUtils.isEmpty(minioConfig.getCdnName()) ? minioConfig.getUrl() + "/" + object : minioConfig.getCdnName() + "/" + object;
        UploadFile sysFile = new UploadFile();
        sysFile.setUrl(url);
        sysFile.setObject(object);

        return sysFile;
    }

    @Override
    public void downloadFile(HttpServletResponse response, String url) {
        OutputStream out = null;
        try {
            if (StringUtils.isNotEmpty(url)) {
                url = url.contains(minioConfig.getBucketName()) ? url
                        .substring(url.indexOf(minioConfig.getBucketName()) + minioConfig.getBucketName().length())
                        : url;
                GetObjectArgs args = GetObjectArgs.builder()
                        .bucket(minioConfig.getBucketName())
                        .object(url)
                        .build();
                GetObjectResponse object = client.getObject(args);
                if (object != null) {
                    String fileName = url.substring(url.lastIndexOf("/") + 1);
                    int length = 0;
                    byte[] buffer = new byte[1024];
                    out = response.getOutputStream();
                    response.reset();
                    response.addHeader("Content-Disposition",
                            "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                    response.setContentType("application/octet-stream");
                    while ((length = object.read(buffer)) > 0) {
                        out.write(buffer, 0, length);
                    }
                    out.flush();
                }
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    log.error("out close err.", e);
                }
            }
        }
    }

    /**
     * 获取文件信息
     *
     * @param minIoClient MinIO链接
     * @param bucketName  bucket名称
     * @param objectName  文件名称
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
     */
    public static StatObjectResponse getObjectInfo(MinioClient minIoClient, String bucketName, String objectName)
            throws Exception {
        return minIoClient.statObject(StatObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
    }

}
